/*
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var bannyUploader_isIE  = (navigator.appVersion.indexOf("MSIE") != -1) ? true : false;
var bannyUploader_isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
var bannyUploader_isOpera = (navigator.userAgent.indexOf("Opera") != -1) ? true : false;

var bannyUploader_requiredMajorVersion = 9;
var bannyUploader_requiredMinorVersion = 0;
var bannyUploader_requiredRevision = 28;

if(typeof(jslog) == 'undefined') jslog = false;

var banny_uploader = null; // instance

/**
 * bannyUploader object.
 */
bannyUploader = function() {
	if(jslog) jslog.info('Instance bannyUploader! ');
	
	// upload url
	this.url = null;
	this.allowUI = false;
	this.target = document.body;
	this.filter = null;
	
	/*----------------------- events begins -- */
	/**
	 * Dispatched periodically during the file upload operation. 
	 * The event have two attributes: bytesTotal, bytesLoaded.
	 */
	this.onProgress = function(event) {
		if(jslog) jslog.info('Progress event: bytesTotal -> ' + event.bytesTotal + ' bytesLoaded -> ' + bytesLoaded);
	};
	
	/**
	 * Dispatched when download is complete or when upload generates an HTTP status code of 200.
	 */
	this.onComplete = function() {
		if(jslog) jslog.info('Upload complete! ');
	};
	
	/**
	 * Dispatched after data is received from the server after a successful upload.
	 * This event is not dispatched if data is not returned from the server.
	 * The event has a 'data' attribute.
	 */
	this.onCompleteData = function(event) {
		if(jslog) jslog.info('Upload complete and data from server received! ');
	};
	
	/**
	 * The file have these attributes: creationDate, creator, modificationDate, name, size, type
	 */
	this.onFileSelect = function(file) {
		if(jslog) jslog.debug(file.name);
	};
	
	/**
	 * Dispatched when an upload fails.
	 * The event have two attributes: message, code.
	 * <ul>
	 * <li>code: 0x85, message: 'No file selected to upload! '</li>
	 * <li>code: 0x86, message: 'The upload url not specified! '</li>
	 * <li>code: 0x87, message: 'Current uploads encounter i/o error! '</li>
	 * <li>code: 0x88, message: 'Current uploads encounter security error! '</li>
	 * </ul>
	 */
	this.onError = function(event) {
		if(jslog) jslog.error('Error code: ' + event.code + ' Error message: ' + event.message);
	};
	/*----------------------- events ends -- */
};

/**
 * Create controller of bannyUploader.
 */
bannyUploader.prototype.createController = function() {
	if(jslog) jslog.info('Initialize the controller of bannyUploader! ');
	
	// document.write('<div id="banny_uploader_controller"></div>');
	var hasRequestedVersion = this.detectFlashVer(
		bannyUploader_requiredMajorVersion,
		bannyUploader_requiredMinorVersion,
		bannyUploader_requiredRevision
	);
	if(jslog) jslog.debug('Has requested version: ' + hasRequestedVersion);
	if(hasRequestedVersion) {
		var ret = this.AC_GetArgs(
			arguments, ".swf", "movie", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000",
			"application/x-shockwave-flash"
		);
		if(jslog) jslog.debug('Has requested flash player version! ' + ret);
		return this.AC_Generateobj(ret.objAttrs, ret.params, ret.embedAttrs);
	} else {
		if(jslog) jslog.error("The browser don't have a required flash player! ");
		return '';
	}
};

/**
 * Set controller.
 */
bannyUploader.prototype.setController = function(url) {
	if(jslog) jslog.info('Set customized controller url: ' + url);
	
	var wrapper = document.getElementById('banny_uploader_controller');
	if(wrapper) {
		if (bannyUploader_isIE && bannyUploader_isWin && !bannyUploader_isOpera) {
			wrapper.removeNode();
		} else {
			// wrapper.id = 'id' + Math.random();
			document.body.removeChild(wrapper);
		}
	}
	var obj = this.createController(
		"src", url == null ? 'bannyUploader.swf' : url,
		"width", this.allowUI ? "100%" : '1px',
		"height", this.allowUI ? "45px" : '1px',
		"align", "middle",
		"id", "banny_uploader_controller",
		"name", "banny_uploader_controller",
		"quality", "high",
		"bgcolor", "#869ca7",
		"allowScriptAccess","always",
		"allowNetworking", "all",
		"swliveconnect", "true",
		"wmode", "transparent",
		"type", "application/x-shockwave-flash",
		"pluginspage", "http://www.adobe.com/go/getflashplayer"
	);
	this.target.innerHTML = this.target.innerHTML + obj;
	
	this.controller = document.getElementById('banny_uploader_controller');
	
	if(this.controller == null) {
		var error = 'Initialize bannyUploader failed because of initialization of the controller! ';
		if(jslog) jslog.error(error);
		//throw error;
	}
};

/**
 * Config bannyUploader.
 * url: The upload url can handler post request. Must have.
 * filter: Specify file filter when browse file. Optional. 
 * controller: May not, default is 'bannyUploader.swf'. Specify the relative path of distrubed swf file.
 * allowUI: May not, default is false. Specify whether use flash ui. 
 * targetId: When specify allowUI, if targetId not specified, `document.body` used.
 * 			if specify the targetId, the flash ui will place into the target of specified.
 *			i.e: document.getElementById(targetId).innerHTML = [flash ui]
 *
 *			If specified the targetId, you should config bannyUploader after document loaded,
 *			i.e <body onload='config();'> or window.onload = config();
 * Sample: { url: 'http://localhost/upload', filter: [], controller: '../build/bannyUploader.swf', allowUI: true, targetId: 'aId' }
 */
bannyUploader.prototype.config = function(config) {
	if(jslog) jslog.info('Config bannyUploader! ');
	
	if(config.url)
		this.url = config.url;
	
	if(typeof(config.allowUI) == 'boolean')
		this.allowUI = config.allowUI;
	
	if(config.targetId) {
		try { this.target = document.getElementById(config.targetId); }
		catch(e) {
			if(jslog) jslog.debug('Caught exception: ' + e);
			this.target = document.body;
			if(jslog) jslog.warn('Specified target was not found: ' + config.targetId);
		}
	}
	
	if(config.filter) this.filter = config.filter;
	
	if(config.controller)
		this.setController(config.controller);
	else
		this.setController();
};

/**
 * Open file browse window.
 * Can have a fileFilter parameter.
 * Sample: banny_uploader.browse([{ name: 'Image', value: '*.jpeg;*.gif;*.bmp' }, { name: 'Flash', value: '*.swf;*.fla' }]);
 */
bannyUploader.prototype.browse = function() {
	if(jslog) jslog.debug('bannyUploader begins browse files! ');
	try {
		if(arguments[0]) this.controller.browse(arguments[0]);
		else this.controller.browse();
	} catch(e) {
		if(jslog) jslog.error('Invoke browse method of bannyUploader failed: ' + e);
	}
};

/**
 * Begin upload. You should browse a file before you can begin upload.
 */
bannyUploader.prototype.upload = function() {
	if(jslog) jslog.debug('bannyUploader begins upload file! ');
	this.controller.upload();
};

/**
 * Cancel current uploads. If no upload begins, nothing to do.
 */
bannyUploader.prototype.cancel = function() {
	if(jslog) jslog.debug('bannyUploader cancel uploads! ');
	this.controller.cancel();
};

bannyUploader.prototype.getSwfVer = function() {
	var flashVer = -1;
	
	if (navigator.plugins != null && navigator.plugins.length > 0) {
		if (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]) {
			var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
			var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;			
			var descArray = flashDescription.split(" ");
			var tempArrayMajor = descArray[2].split(".");
			var versionMajor = tempArrayMajor[0];
			var versionMinor = tempArrayMajor[1];
			if ( descArray[3] != "" ) {
				tempArrayMinor = descArray[3].split("r");
			} else {
				tempArrayMinor = descArray[4].split("r");
			}
			var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
			var flashVer = versionMajor + "." + versionMinor + "." + versionRevision;
		}
	} else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.6") != -1) flashVer = 4;
	// WebTV 2.5 supports Flash 3
	else if (navigator.userAgent.toLowerCase().indexOf("webtv/2.5") != -1) flashVer = 3;
	// older WebTV supports Flash 2
	else if (navigator.userAgent.toLowerCase().indexOf("webtv") != -1) flashVer = 2;
	else if (bannyUploader_isIE && bannyUploader_isWin && !bannyUploader_isOpera ) {
		flashVer = this.controlVersion();
	}	
	return flashVer;
};
bannyUploader.prototype.controlVersion = function() {
	var version;
	var axo;
	var e;

	try {
		axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
		version = axo.GetVariable("$version");
	} catch (e) {}

	if (!version) {
		try {
			axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
			
			version = "WIN 6,0,21,0";

			axo.AllowScriptAccess = "always";

			version = axo.GetVariable("$version");

		} catch (e) {}
	}

	if (!version) {
		try {
			// version will be set for 4.X or 5.X player
			axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
			version = axo.GetVariable("$version");
		} catch (e) {}
	}

	if (!version) {
		try {
			// version will be set for 3.X player
			axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.3");
			version = "WIN 3,0,18,0";
		} catch (e) {}
	}

	if (!version) {
		try {
			// version will be set for 2.X player
			axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
			version = "WIN 2,0,0,11";
		} catch (e) {
			version = -1;
		}
	}
	
	return version;
};
bannyUploader.prototype.detectFlashVer = function(reqMajorVer, reqMinorVer, reqRevision) {
	var versionStr = this.getSwfVer();
	if(jslog) jslog.debug('Version string: ' + versionStr);
	if (versionStr == -1 ) {
		return false;
	} else if (versionStr != 0) {
		if(bannyUploader_isIE && bannyUploader_isWin && !bannyUploader_isOpera) {
			// Given "WIN 2,0,0,11"
			tempArray         = versionStr.split(" "); 	// ["WIN", "2,0,0,11"]
			tempString        = tempArray[1];			// "2,0,0,11"
			versionArray      = tempString.split(",");	// ['2', '0', '0', '11']
		} else {
			versionArray      = versionStr.split(".");
		}
		var versionMajor      = versionArray[0];
		var versionMinor      = versionArray[1];
		var versionRevision   = versionArray[2];

		if (versionMajor > parseFloat(reqMajorVer)) {
			return true;
		} else if (versionMajor == parseFloat(reqMajorVer)) {
			if (versionMinor > parseFloat(reqMinorVer))
				return true;
			else if (versionMinor == parseFloat(reqMinorVer)) {
				if (versionRevision >= parseFloat(reqRevision))
					return true;
			}
		}
		return false;
	}
};
bannyUploader.prototype.AC_GetArgs = function(args, ext, srcParamName, classid, mimeType) {
	var ret = new Object();
	ret.embedAttrs = new Object();
	ret.params = new Object();
	ret.objAttrs = new Object();
	
	for (var i=0; i < args.length; i=i+2){
		var currArg = args[i].toLowerCase();
		
		switch (currArg){
			case "classid":
				break;
			case "pluginspage":
				ret.embedAttrs[args[i]] = args[i+1];
				break;
			case "src":
			case "movie":
				args[i+1] = this.AC_AddExtension(args[i+1], ext);
				ret.embedAttrs["src"] = args[i+1];
				ret.params[srcParamName] = args[i+1];
				break;
			case "onafterupdate":
			case "onbeforeupdate":
			case "onblur":
			case "oncellchange":
			case "onclick":
			case "ondblClick":
			case "ondrag":
			case "ondragend":
			case "ondragenter":
			case "ondragleave":
			case "ondragover":
			case "ondrop":
			case "onfinish":
			case "onfocus":
			case "onhelp":
			case "onmousedown":
			case "onmouseup":
			case "onmouseover":
			case "onmousemove":
			case "onmouseout":
			case "onkeypress":
			case "onkeydown":
			case "onkeyup":
			case "onload":
			case "onlosecapture":
			case "onpropertychange":
			case "onreadystatechange":
			case "onrowsdelete":
			case "onrowenter":
			case "onrowexit":
			case "onrowsinserted":
			case "onstart":
			case "onscroll":
			case "onbeforeeditfocus":
			case "onactivate":
			case "onbeforedeactivate":
			case "ondeactivate":
			case "type":
			case "codebase":
				ret.objAttrs[args[i]] = args[i+1];
				break;
			case "id":
			case "width":
			case "height":
			case "align":
			case "vspace": 
			case "hspace":
			case "class":
			case "title":
			case "accesskey":
			case "name":
			case "tabindex":
				ret.embedAttrs[args[i]] = ret.objAttrs[args[i]] = args[i+1];
				break;
			default:
				ret.embedAttrs[args[i]] = ret.params[args[i]] = args[i+1];
		}
	}
	ret.objAttrs["classid"] = classid;
	if (mimeType) ret.embedAttrs["type"] = mimeType;
	return ret;
};
bannyUploader.prototype.AC_Generateobj = function(objAttrs, params, embedAttrs) {
	var str = '';
    if (bannyUploader_isIE && bannyUploader_isWin && !bannyUploader_isOpera) {
  		str += '<object ';
  		for (var i in objAttrs)
  			str += i + '="' + objAttrs[i] + '" ';
  		str += '>';
  		for (var i in params)
  			str += '<param name="' + i + '" value="' + params[i] + '" /> ';
  		str += '</object>';
    } else {
  		str += '<embed ';
  		for (var i in embedAttrs)
  			str += i + '="' + embedAttrs[i] + '" ';
  		str += '></embed>';
    }
	
	if(jslog) jslog.debug(str);
    return str;
};
bannyUploader.prototype.AC_AddExtension = function(src, ext) {
	if (src.toLowerCase().lastIndexOf('.swf') != -1)
		return src;
	else
		return src + ext;
};

/*--------------------------------- Invoked by flash begins --*/
function bannyUploader_onProgress(event) {
	if(typeof(banny_uploader.onProgress) == 'function') banny_uploader.onProgress(event);
}
function bannyUploader_onComplete() {
	if(typeof(banny_uploader.onComplete) == 'function') banny_uploader.onComplete();
}
function bannyUploader_onCompleteData(event) {
	if(typeof(banny_uploader.onCompleteData) == 'function') banny_uploader.onCompleteData(event);
}
function bannyUploader_onFileSelect(file) {
	if(typeof(banny_uploader.onFileSelect) == 'function') banny_uploader.onFileSelect(file);
}
function bannyUploader_onError(event) {
	if(jslog) jslog.info('bannyUploader_onError invoked by flash! ');
	
	if(typeof(banny_uploader.onError) == 'function') banny_uploader.onError(event);
}
function bannyUploader_getUrl() {
	if(jslog) jslog.debug('Return upload url to flash: ' + banny_uploader.url);
	return banny_uploader.url;
}
function bannyUploader_getFilter() {
	return banny_uploader.filter;
}
/*--------------------------------- Invoked by flash ends --*/

/**
 * Initialize the instance.
 */
banny_uploader = new bannyUploader();